
#include <BLabel>
#include <BStyle>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BGridLayout>
#include <BScrollBar>

#include "PropertyBox.h"

PropertyBox::PropertyBox(BWidget* parent) : BDialog(parent)
{
	this->removeTitleButton(Button_Close);
	BGridLayout* nameLayout = new BGridLayout();
	nameLayout->setColumnPolicy(0, Policy_Preferred | Policy_Expanding);
	{
		BLabel* nameLabel = new BLabel("name");
		_nameComboBox = new BComboBox();
		_nameComboBox->setReadOnly(false);

		BLabel* formatLabel = new BLabel("format");
		_formatEdit = new BLineEdit();

		nameLayout->setWidget(0, 0, nameLabel);
		nameLayout->setWidget(0, 1, _nameComboBox);
		nameLayout->setWidget(1, 0, formatLabel);
		nameLayout->setWidget(1, 1, _formatEdit);
	}

	_attribTable = new BTableWidget();
	_attribTable->setColumnCount(2);
	_attribTable->setColumnLabel(0, "attrib");
	_attribTable->setColumnLabel(1, "value");
	_attribTable->setGridStyle(Grid_Crossing);
	_attribTable->verticalScrollBar()->setFixedWidth(2);
	_attribTable->verticalScrollBar()->setWidthPolicy(Policy_Fixed);

	_attribEdit = new BLineEdit(_attribTable);
	_attribEdit->setVisible(false);
	
	_textEdit = new BTextEdit();
	_textEdit->setReadOnly(true);
	_textEdit->setStyleSheet("handle-size:12px");

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->setSpacing(3);
	vlayout->addLayout(nameLayout);
	vlayout->addWidget(_attribTable, 1000);
	vlayout->addWidget(_textEdit, 1000);

	connect(_nameComboBox, Signal_EditFinished, &PropertyBox::slotNameEditFinished);
	connect(_nameComboBox, Signal_CurrentChanged, &PropertyBox::slotComboCurrentChanged);
	connect(_formatEdit, Signal_EditFinished, &PropertyBox::slotFormatEditFinished);
	connect(_attribTable, Signal_DoubleClicked, &PropertyBox::slotAttribItemDoubleClicked);
	connect(_attribEdit, Signal_EditFinished, &PropertyBox::slotAttribEditFinished);
	connect(_attribEdit, Signal_Focused, &PropertyBox::slotAttribEditFocused);

	attachHtmlWidget(0);
}
PropertyBox::~PropertyBox()
{

}

void PropertyBox::attachHtmlWidget(BHtmlWidget* htmlWidget)
{
	if (_htmlWidget != htmlWidget)
	{
		_nameComboBox->clearItems();
		_attribTable->clearItems();
		_textEdit->setText(BString());
		_formatEdit->setText(BString());
		if (_htmlWidget)
		{
			disconnect(_htmlWidget);
			this->setTitle(BString());
		}
		_htmlWidget = htmlWidget;
		if (_htmlWidget)
		{
			this->setTitle(_htmlWidget->title());
			connect(_htmlWidget, Signal_ItemSelected, &PropertyBox::slotHtmlItemSelected);
		}
	}
	bool enabled = _htmlWidget != 0;
	_nameComboBox->setEnabled(enabled);
	_formatEdit->setEnabled(enabled);
	_attribTable->setEnabled(enabled);
	_textEdit->setEnabled(enabled);
}

void PropertyBox::slotNameEditFinished(BObject* object, const BValue& value)
{
	const BString& name = _nameComboBox->text();
	_htmlItem->setName(name);
}
void PropertyBox::slotHtmlItemSelected(BObject* object, const BValue& value)
{
	BHtmlItem* item = value;
	if (_htmlItem != item)
	{
		_nameComboBox->clearItems();
		_formatEdit->setText(BString());
		_attribTable->clearItems();
		_textEdit->setText(BString());
		if (_htmlItem)
			disconnect(_htmlItem);
		_htmlItem = item;
		if (_htmlItem)
		{
			connect(_htmlItem, Signal_TextChanged, &PropertyBox::slotHtmlItemTextChanged);
			const BStyle* style = this->realStyle();
			while (item)
			{
				BIcon* icon = style->icon(item->name());
				_nameComboBox->addItem(icon, item->name(), item);
				item = item->parent();
			}
			BString format = _htmlItem->format();
			if (format.size())
			{
				format.replace("\n", "\\n");
				_formatEdit->setText(format);
			}
			const BMap<BString, BString>& attribSet = _htmlItem->attribSet();
			_attribTable->setRowCount(attribSet.size() + 1);
			for (auto it = attribSet.begin(); it.valid(); ++it)
			{
				const BString& attribName = it.key();
				const BString& attribValue = it.value();
				_attribTable->setItem(it.index(), 0, attribName);
				_attribTable->setItem(it.index(), 1, attribValue);
			}
			for (int r = 0; r < _attribTable->rowCount(); r++)
			{
				_attribTable->setRowLabel(r, r);
			}
			_textEdit->setText(_htmlItem->text());
		}
	}
}
void PropertyBox::slotHtmlItemTextChanged(BObject* object, const BValue& value)
{
	if (_htmlItem != object)
		return;
	_textEdit->setText(_htmlItem->text());
}
void PropertyBox::slotComboCurrentChanged(BObject* object, const BValue& value)
{
	int current = value;
	BHtmlItem* item = _nameComboBox->value();
	item->setSelected(true);
}
void PropertyBox::slotFormatEditFinished(BObject* object, const BValue& value)
{
	BString format = value;
	format.replace("\\n", "\n");
	if (_htmlItem)
		_htmlItem->setFormat(format);
}
void PropertyBox::slotAttribItemDoubleClicked(BObject* object, const BValue& value)
{
	const BPoint& pos = value;
	BTableItem* item = _attribTable->itemAt(pos);
	if (!item)
	{
		int row = _attribTable->rowAt(pos.y());
		int column = _attribTable->columnAt(pos.x());
		if (row < 0 || column < 0)
			return;
		item = new BTableItem();
		_attribTable->setItem(row, column, item);
		item->setSelected(true);
	}
	BRect rect = _attribTable->cellRect(item->row(), item->column());
	_attribEdit->setRect(rect);
	_attribEdit->setText(item->text());
	_attribEdit->popup();
	_attribEdit->setFocused(true);
}
void PropertyBox::slotAttribEditFinished(BObject* object, const BValue& value)
{
	_attribEdit->hide();
	BTableItem* item = _attribTable->selectedItem();
	item->setText(_attribEdit->text());

	int row = item->row();
	BTableItem* nameItem = _attribTable->item(row, 0);
	BTableItem* valueItem = _attribTable->item(row, 1);
	if (!nameItem || !valueItem)
		return;

	const BMap<BString, BString>& attribSet = _htmlItem->attribSet();
	if (item->column() == 0 && attribSet.size() > row)
	{
		//_htmlItem->renameAttrib(_htmlItem->attribName(row), nameItem->text());
	}
	_htmlItem->setAttrib(nameItem->text(), valueItem->text());
	this->emit(Signal_ItemEdited, _htmlItem);
}
void PropertyBox::slotAttribEditFocused(BObject* object, const BValue& value)
{
	if (value == false)
	{
		_attribEdit->hide();
	}
}

void PropertyBox::styleEvent(const BEvent& event)
{
	const BStyle* style = this->realStyle();
	if (style)
	{
	}
}
